home *** CD-ROM | disk | FTP | other *** search
/ Chip 2000 April / Chip CMCD0400.iso / SOFTWARE / Freeware / Programare / Bass / 3DTEST.C next >
Encoding:
C/C++ Source or Header  |  1999-07-21  |  13.1 KB  |  440 lines

  1. /* BASS 3D Test (rev.2), copyright (c) 1999 Ian Luck.
  2. =====================================================
  3. Other source: 3dtest.rc
  4. Imports: bass.lib, kernel32.lib, user32.lib, comdlg32.lib, gdi32.lib
  5. */
  6.  
  7. #include <windows.h>
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10. #include "bass.h"
  11. #include "3dtest.h"
  12.  
  13. static HWND win=NULL;
  14. static HINSTANCE inst;
  15.  
  16. /* channel (sample/music) info structure */
  17. typedef struct {
  18.     HSAMPLE sample;            // sample handle (NULL if it's a MOD music)
  19.     DWORD channel;            // the channel
  20.     BASS_3DVECTOR pos,vel;    // position,velocity
  21.     int dir;                // direction of the channel
  22. } Channel;
  23.  
  24. static Channel *chans=NULL;        // the channels
  25. static int chanc=0,chan=-1;        // number of channels, current channel
  26. static HBRUSH brush1,brush2;    // brushes
  27.  
  28. #define TIMERPER    50            // timer period (ms)
  29. #define MAXDIST        500.0        // maximum distance of the channels (m)
  30. #define SPEED        5.0            // speed of the channels' movement (m/s)
  31.  
  32. /* Display error dialogs */
  33. static void Error(char *es)
  34. {
  35.     char mes[200];
  36.     sprintf(mes,"%s\n(error code: %d)",es,BASS_ErrorGetCode());
  37.     MessageBox(win,mes,"Error",0);
  38. }
  39.  
  40. /* Messaging macros */
  41. #define ITEM(id) GetDlgItem(win,id)
  42. #define MESS(id,m,w,l) SendMessage(ITEM(id),m,(WPARAM)w,(LPARAM)l)
  43. #define LM(m,w,l) MESS(ID_LIST,m,w,l)
  44. #define EM(m,w,l) MESS(ID_EAX,m,w,l)
  45.  
  46. void CALLBACK Update(HWND win, UINT m, UINT i, DWORD t)
  47. {
  48.     HDC dc;
  49.     RECT r;
  50.     int c,x,y,cx,cy;
  51.     int save;
  52.     HPEN pen;
  53.  
  54.     win=ITEM(ID_DISPLAY);
  55.     dc=GetDC(win);
  56.     save=SaveDC(dc);
  57.     GetClientRect(win,&r);
  58.     cx=r.right/2;
  59.     cy=r.bottom/2;
  60.  
  61.     /* Draw center circle */
  62.     SelectObject(dc,GetStockObject(GRAY_BRUSH));
  63.     Ellipse(dc,cx-4,cy-4,cx+4,cy+4);
  64.  
  65.     pen=CreatePen(PS_SOLID,2,GetSysColor(COLOR_BTNFACE));
  66.     SelectObject(dc,pen);
  67.  
  68.     for (c=0;c<chanc;c++) {
  69.         /* If the channel's playing then update it's position */
  70.         if (BASS_ChannelIsActive(chans[c].channel)) {
  71.             /* Check if channel has reached the max distance */
  72.             if (chans[c].pos.z>=MAXDIST || chans[c].pos.z<=-MAXDIST)
  73.                 chans[c].vel.z=-chans[c].vel.z;
  74.             if (chans[c].pos.x>=MAXDIST || chans[c].pos.x<=-MAXDIST)
  75.                 chans[c].vel.x=-chans[c].vel.x;
  76.             /* Update channel position */
  77.             chans[c].pos.z+=chans[c].vel.z*(float)TIMERPER/1000.0;
  78.             chans[c].pos.x+=chans[c].vel.x*(float)TIMERPER/1000.0;
  79.             BASS_ChannelSet3DPosition(chans[c].channel,&chans[c].pos,NULL,&chans[c].vel);
  80.         }
  81.         /* Draw the channel position indicator */
  82.         x=cx+(int)((float)cx*chans[c].pos.x/(float)(MAXDIST+40));
  83.         y=cy-(int)((float)cy*chans[c].pos.z/(float)(MAXDIST+40));
  84.         if (chan==c)
  85.             SelectObject(dc,brush1);
  86.         else
  87.             SelectObject(dc,brush2);
  88.         Ellipse(dc,x-6,y-6,x+6,y+6);
  89.     }
  90.     /* Apply the 3D changes */
  91.     BASS_Apply3D();
  92.  
  93.     RestoreDC(dc,save);
  94.     DeleteObject(pen);
  95.     ReleaseDC(win,dc);
  96. }
  97.  
  98. /* Update the button states */
  99. static void UpdateButtons()
  100. {
  101.     int a;
  102.     EnableWindow(ITEM(ID_REMOVE),chan==-1?FALSE:TRUE);
  103.     EnableWindow(ITEM(ID_PLAY),chan==-1?FALSE:TRUE);
  104.     EnableWindow(ITEM(ID_STOP),chan==-1?FALSE:TRUE);
  105.     for (a=0;a<5;a++)
  106.         EnableWindow(ITEM(ID_LEFT+a),chan==-1?FALSE:TRUE);
  107.     if (chan!=-1) {
  108.         MESS(ID_LEFT,BM_SETCHECK,chans[chan].dir==ID_LEFT?BST_CHECKED:BST_UNCHECKED,0);
  109.         MESS(ID_RIGHT,BM_SETCHECK,chans[chan].dir==ID_RIGHT?BST_CHECKED:BST_UNCHECKED,0);
  110.         MESS(ID_FRONT,BM_SETCHECK,chans[chan].dir==ID_FRONT?BST_CHECKED:BST_UNCHECKED,0);
  111.         MESS(ID_BEHIND,BM_SETCHECK,chans[chan].dir==ID_BEHIND?BST_CHECKED:BST_UNCHECKED,0);
  112.         MESS(ID_NONE,BM_SETCHECK,!chans[chan].dir?BST_CHECKED:BST_UNCHECKED,0);
  113.     }
  114. }
  115.  
  116. BOOL CALLBACK dialogproc(HWND h,UINT m,WPARAM w,LPARAM l)
  117. {
  118.     static OPENFILENAME ofn;
  119.     static char path[MAX_PATH];
  120.  
  121.     switch (m) {
  122.         case WM_COMMAND:
  123.             switch (LOWORD(w)) {
  124.                 case ID_EAX:
  125.                     /* Change the EAX environment */
  126.                     if (HIWORD(w)==CBN_SELCHANGE) {
  127.                         int s=EM(CB_GETCURSEL,0,0);
  128.                         switch (s) {
  129.                             case 0:
  130.                                 BASS_SetEAXParameters(-1,0.0,-1.0,-1.0);
  131.                                 break;
  132.                             case 1:
  133.                                 BASS_SetEAXParameters(EAX_PRESET_GENERIC);
  134.                                 break;
  135.                             case 2:
  136.                                 BASS_SetEAXParameters(EAX_PRESET_PADDEDCELL);
  137.                                 break;
  138.                             case 3:
  139.                                 BASS_SetEAXParameters(EAX_PRESET_ROOM);
  140.                                 break;
  141.                             case 4:
  142.                                 BASS_SetEAXParameters(EAX_PRESET_BATHROOM);
  143.                                 break;
  144.                             case 5:
  145.                                 BASS_SetEAXParameters(EAX_PRESET_LIVINGROOM);
  146.                                 break;
  147.                             case 6:
  148.                                 BASS_SetEAXParameters(EAX_PRESET_STONEROOM);
  149.                                 break;
  150.                             case 7:
  151.                                 BASS_SetEAXParameters(EAX_PRESET_AUDITORIUM);
  152.                                 break;
  153.                             case 8:
  154.                                 BASS_SetEAXParameters(EAX_PRESET_CONCERTHALL);
  155.                                 break;
  156.                             case 9:
  157.                                 BASS_SetEAXParameters(EAX_PRESET_CAVE);
  158.                                 break;
  159.                             case 10:
  160.                                 BASS_SetEAXParameters(EAX_PRESET_ARENA);
  161.                                 break;
  162.                             case 11:
  163.                                 BASS_SetEAXParameters(EAX_PRESET_HANGAR);
  164.                                 break;
  165.                             case 12:
  166.                                 BASS_SetEAXParameters(EAX_PRESET_CARPETEDHALLWAY);
  167.                                 break;
  168.                             case 13:
  169.                                 BASS_SetEAXParameters(EAX_PRESET_HALLWAY);
  170.                                 break;
  171.                             case 14:
  172.                                 BASS_SetEAXParameters(EAX_PRESET_STONECORRIDOR);
  173.                                 break;
  174.                             case 15:
  175.                                 BASS_SetEAXParameters(EAX_PRESET_ALLEY);
  176.                                 break;
  177.                             case 16:
  178.                                 BASS_SetEAXParameters(EAX_PRESET_FOREST);
  179.                                 break;
  180.                             case 17:
  181.                                 BASS_SetEAXParameters(EAX_PRESET_CITY);
  182.                                 break;
  183.                             case 18:
  184.                                 BASS_SetEAXParameters(EAX_PRESET_MOUNTAINS);
  185.                                 break;
  186.                             case 19:
  187.                                 BASS_SetEAXParameters(EAX_PRESET_QUARRY);
  188.                                 break;
  189.                             case 20:
  190.                                 BASS_SetEAXParameters(EAX_PRESET_PLAIN);
  191.                                 break;
  192.                             case 21:
  193.                                 BASS_SetEAXParameters(EAX_PRESET_PARKINGLOT);
  194.                                 break;
  195.                             case 22:
  196.                                 BASS_SetEAXParameters(EAX_PRESET_SEWERPIPE);
  197.                                 break;
  198.                             case 23:
  199.                                 BASS_SetEAXParameters(EAX_PRESET_UNDERWATER);
  200.                                 break;
  201.                             case 24:
  202.                                 BASS_SetEAXParameters(EAX_PRESET_DRUGGED);
  203.                                 break;
  204.                             case 25:
  205.                                 BASS_SetEAXParameters(EAX_PRESET_DIZZY);
  206.                                 break;
  207.                             case 26:
  208.                                 BASS_SetEAXParameters(EAX_PRESET_PSYCHOTIC);
  209.                                 break;
  210.                         }
  211.                     }
  212.                     return 1;
  213.                 case ID_LIST:
  214.                     /* Change the selected channel */
  215.                     if (HIWORD(w)!=LBN_SELCHANGE) break;
  216.                     chan=LM(LB_GETCURSEL,0,0);
  217.                     if (chan==LB_ERR) chan=-1;
  218.                     UpdateButtons();
  219.                     return 1;
  220.                 case ID_LEFT:
  221.                     if (HIWORD(w)!=BN_CLICKED) break;
  222.                     chans[chan].dir=ID_LEFT;
  223.                     /* Make the channel move past the left of you */
  224.                     /* Set speed in m/s */
  225.                     chans[chan].vel.z=SPEED*1000.0/(float)TIMERPER;
  226.                     chans[chan].vel.x=0.0;
  227.                     /* Set positon to the left */
  228.                     chans[chan].pos.x=-20.0;
  229.                     /* Reset display */
  230.                     InvalidateRect(GetDlgItem(h,ID_DISPLAY),NULL,TRUE);
  231.                     return 1;
  232.                 case ID_RIGHT:
  233.                     if (HIWORD(w)!=BN_CLICKED) break;
  234.                     chans[chan].dir=ID_RIGHT;
  235.                     /* Make the channel move past the right of you */
  236.                     chans[chan].vel.z=SPEED*1000.0/(float)TIMERPER;
  237.                     chans[chan].vel.x=0.0;
  238.                     /* Set positon to the right */
  239.                     chans[chan].pos.x=20.0;
  240.                     InvalidateRect(GetDlgItem(h,ID_DISPLAY),NULL,TRUE);
  241.                     return 1;
  242.                 case ID_FRONT:
  243.                     if (HIWORD(w)!=BN_CLICKED) break;
  244.                     chans[chan].dir=ID_FRONT;
  245.                     /* Make the channel move past the front of you */
  246.                     chans[chan].vel.x=SPEED*1000.0/(float)TIMERPER;
  247.                     chans[chan].vel.z=0.0;
  248.                     /* Set positon to in front */
  249.                     chans[chan].pos.z=20.0;
  250.                     InvalidateRect(GetDlgItem(h,ID_DISPLAY),NULL,TRUE);
  251.                     return 1;
  252.                 case ID_BEHIND:
  253.                     if (HIWORD(w)!=BN_CLICKED) break;
  254.                     chans[chan].dir=ID_BEHIND;
  255.                     /* Make the channel move past the back of you */
  256.                     chans[chan].vel.x=SPEED*1000.0/(float)TIMERPER;
  257.                     chans[chan].vel.z=0.0;
  258.                     /* Set positon to behind */
  259.                     chans[chan].pos.z=-20.0;
  260.                     InvalidateRect(GetDlgItem(h,ID_DISPLAY),NULL,TRUE);
  261.                     return 1;
  262.                 case ID_NONE:
  263.                     if (HIWORD(w)!=BN_CLICKED) break;
  264.                     chans[chan].dir=0;
  265.                     /* Make the channel stop moving */
  266.                     chans[chan].vel.x=chans[chan].vel.z=0.0;
  267.                     return 1;
  268.                 case ID_ADD:
  269.                     {
  270.                         char file[MAX_PATH]="";
  271.                         DWORD newchan;
  272.                         ofn.lpstrFile=file;
  273.                         if (GetOpenFileName(&ofn)) {
  274.                             memcpy(path,file,ofn.nFileOffset);
  275.                             path[ofn.nFileOffset-1]=0;
  276.                             /* Load a music from "file" with 3D enabled, and make it loop & use ramping */
  277.                             if (newchan=BASS_MusicLoad(FALSE,file,0,0,BASS_MUSIC_RAMP|BASS_MUSIC_LOOP|BASS_MUSIC_3D)) {
  278.                                 Channel *c;
  279.                                 chanc++;
  280.                                 chans=(Channel*)realloc((void*)chans,chanc*sizeof(Channel));
  281.                                 c=chans+chanc-1;
  282.                                 memset(c,0,sizeof(Channel));
  283.                                 c->channel=newchan;
  284.                                 LM(LB_ADDSTRING,0,file);
  285.                                 /* Set the min/max distance to 15/1000 meters */
  286.                                 BASS_ChannelSet3DAttributes(newchan,-1,15.0,1000.0,-1,-1,-1);
  287.                             } else
  288.                             /* Load a sample from "file" with 3D enabled, and make it loop */
  289.                             if (newchan=BASS_SampleLoad(FALSE,file,0,0,1,BASS_SAMPLE_LOOP|BASS_SAMPLE_3D)) {
  290.                                 Channel *c;
  291.                                 BASS_SAMPLE sam;
  292.                                 chanc++;
  293.                                 chans=(Channel*)realloc((void*)chans,chanc*sizeof(Channel));
  294.                                 c=chans+chanc-1;
  295.                                 memset(c,0,sizeof(Channel));
  296.                                 c->sample=newchan;
  297.                                 LM(LB_ADDSTRING,0,file);
  298.                                 /* Set the min/max distance to 15/1000 meters */
  299.                                 BASS_SampleGetInfo(newchan,&sam);
  300.                                 sam.mindist=15.0;
  301.                                 sam.maxdist=1000.0;
  302.                                 BASS_SampleSetInfo(newchan,&sam);
  303.                             } else
  304.                                 Error("Can't load file");
  305.                         }
  306.                     }
  307.                     return 1;
  308.                 case ID_REMOVE:
  309.                     {
  310.                         Channel *c=chans+chan;
  311.                         if (c->sample)
  312.                             BASS_SampleFree(c->sample);
  313.                         else
  314.                             BASS_MusicFree(c->channel);
  315.                         memcpy(c,c+1,(chanc-chan-1)*sizeof(Channel));
  316.                         chanc--;
  317.                         LM(LB_DELETESTRING,chan,0);
  318.                         chan=-1;
  319.                         UpdateButtons();
  320.                         InvalidateRect(GetDlgItem(h,ID_DISPLAY),NULL,TRUE);
  321.                     }
  322.                     return 1;
  323.                 case ID_PLAY:
  324.                     {
  325.                         if (chans[chan].sample) {
  326.                             if (!chans[chan].channel)
  327.                                 chans[chan].channel=BASS_SamplePlay3D(chans[chan].sample,&chans[chan].pos,NULL,&chans[chan].vel);
  328.                         } else
  329.                             BASS_MusicPlay(chans[chan].channel);
  330.                     }
  331.                     return 1;
  332.                 case ID_STOP:
  333.                     BASS_ChannelStop(chans[chan].channel);
  334.                     if (chans[chan].sample) chans[chan].channel=0;
  335.                     return 1;
  336.                 case IDCANCEL:
  337.                     DestroyWindow(h);
  338.                     return 1;
  339.             }
  340.             break;
  341.  
  342.         case WM_INITDIALOG:
  343.             win=h;
  344.             brush1=CreateSolidBrush(0xff);
  345.             brush2=CreateSolidBrush(0x7f);
  346.  
  347.             EM(CB_ADDSTRING,0,"Off");
  348.             EM(CB_ADDSTRING,0,"Generic");
  349.             EM(CB_ADDSTRING,0,"Padded Cell");
  350.             EM(CB_ADDSTRING,0,"Room");
  351.             EM(CB_ADDSTRING,0,"Bathroom");
  352.             EM(CB_ADDSTRING,0,"Living Room");
  353.             EM(CB_ADDSTRING,0,"Stone Room");
  354.             EM(CB_ADDSTRING,0,"Auditorium");
  355.             EM(CB_ADDSTRING,0,"Concert Hall");
  356.             EM(CB_ADDSTRING,0,"Cave");
  357.             EM(CB_ADDSTRING,0,"Arena");
  358.             EM(CB_ADDSTRING,0,"Hangar");
  359.             EM(CB_ADDSTRING,0,"Carpeted Hallway");
  360.             EM(CB_ADDSTRING,0,"Hallway");
  361.             EM(CB_ADDSTRING,0,"Stone Corridor");
  362.             EM(CB_ADDSTRING,0,"Alley");
  363.             EM(CB_ADDSTRING,0,"Forest");
  364.             EM(CB_ADDSTRING,0,"City");
  365.             EM(CB_ADDSTRING,0,"Mountains");
  366.             EM(CB_ADDSTRING,0,"Quarry");
  367.             EM(CB_ADDSTRING,0,"Plain");
  368.             EM(CB_ADDSTRING,0,"Parking Lot");
  369.             EM(CB_ADDSTRING,0,"Sewer Pipe");
  370.             EM(CB_ADDSTRING,0,"Under Water");
  371.             EM(CB_ADDSTRING,0,"Drugged");
  372.             EM(CB_ADDSTRING,0,"Dizzy");
  373.             EM(CB_ADDSTRING,0,"Psychotic");
  374.             EM(CB_SETCURSEL,0,0);
  375.  
  376.             SetTimer(h,1,TIMERPER,&Update);
  377.             GetCurrentDirectory(MAX_PATH,path);
  378.             memset(&ofn,0,sizeof(ofn));
  379.             ofn.lStructSize=sizeof(ofn);
  380.             ofn.hwndOwner=h;
  381.             ofn.hInstance=inst;
  382.             ofn.nMaxFile=MAX_PATH;
  383.             ofn.lpstrInitialDir=path;
  384.             ofn.Flags=OFN_HIDEREADONLY|OFN_EXPLORER;
  385.             ofn.lpstrFilter="wav/xm/mod/s3m/it/mtm\0*.wav;*.xm;*.mod;*.s3m;*.it;*.mtm\0"
  386.                 "All files\0*.*\0\0";
  387.             return 1;
  388.  
  389.         case WM_DESTROY:
  390.             KillTimer(h,1);
  391.             DeleteObject(brush1);
  392.             DeleteObject(brush2);
  393.             PostQuitMessage(0);
  394.             return 1;
  395.     }
  396.     return 0;
  397. }
  398.  
  399. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
  400. {
  401.     MSG msg;
  402.     inst=hInstance;
  403.  
  404. /* Check that BASS 0.6 was loaded */
  405.     if (BASS_GetVersion()!=MAKELONG(0,6)) {
  406.         Error("BASS version 0.6 was not loaded");
  407.         return 0;
  408.     }
  409.  
  410.     if (!CreateDialog(hInstance,MAKEINTRESOURCE(1000),NULL,&dialogproc)) {
  411.         Error("Can't create window");
  412.         return 0;
  413.     }
  414.  
  415. /* Initialize output device - default device, 44100hz, stereo, 16 bits, with 3D funtionality */
  416.     if (!BASS_Init(-1,44100,BASS_DEVICE_3D,win)) Error("Can't initialize output device");
  417. /* Use meters as distance unit, 2x real world rolloff, real doppler effect */
  418.     BASS_Set3DFactors(1.0,2.0,1.0);
  419. /* Turn EAX off (volume=0.0), if error then EAX is not supported */
  420.     if (!BASS_SetEAXParameters(-1,0.0,-1.0,-1.0))
  421.         EnableWindow(GetDlgItem(win,ID_EAX),FALSE);
  422.  
  423.     BASS_Start();    /* Start digital output */
  424.  
  425.     while (1) {
  426.         if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
  427.             if (!GetMessage(&msg, NULL, 0, 0))
  428.                 break;
  429.             TranslateMessage(&msg);
  430.             DispatchMessage(&msg);
  431.         } else
  432.             WaitMessage();
  433.     }
  434.     
  435.     BASS_Stop();    /* Stop digital output */
  436.     BASS_Free();
  437.     if (chans) free(chans);
  438.     return 0;
  439. }
  440.